<!DOCTYPE html>
<html lang="cn">

<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="常用工具整理 体检工具 生产环境不同于开发环境，生产环境往往是一个很干净的、只保留了相关依赖的环境，而且需要运行很长的时间。而开发环境属于实验室性质的，类库比较齐全，只跑个单元测试或者benchmark之类的，运行时间很短。所以开发环境中很小的问题比如内存泄漏几KB，在生产环境随着时间的累积或者成千上万的访问，可能会把垃圾回收器搞崩溃。这种情况如果我们不擅于使用工具可能找不到任何问题。
另外，开发环境我们可以使用100%的资源，但生产环境一定要预留一些资源用来做调度、预警之类的。
dstat 它能实时查看一些基本信息，默认情况下它会包括:
 CPU基本信息(用户使用时间、系统使用时间、空闲时间等) 磁盘基本信息(读、写) 网络基本信息(接受、发送) 换入换出信息 系统基本信息(中断的次数、上下文切换的次数)  如下所示: [ubuntu] ~/.mac $ dstat You did not select any stats, using -cdngy by default. --total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai stl| read writ| recv send| in out | int csw 0 0 100 0 0|2797B 597B| 0 0 | 0 0 | 90 236 0 0 100 0 0| 0 0 | 0 0 | 0 0 | 140 323 0 0 100 0 0| 0 0 | 0 0 | 0 0 | 163 376 0 1 100 0 0| 0 0 | 0 0 | 0 0 | 169 391"><meta property="og:title" content="常用工具整理" />
<meta property="og:description" content="" />
<meta property="og:type" content="website" />
<meta property="og:url" content="/docs/other/tools/" />

<title>常用工具整理 | Home</title>
<link rel="icon" href="/favicon.png" type="image/x-icon">
<link rel="stylesheet" href="/book.min.63eb88daa545365405ecdbb21033286a325c60a36cfa6d22d21e7c3bc9286941.css" integrity="sha256-Y&#43;uI2qVFNlQF7NuyEDMoajJcYKNs&#43;m0i0h58O8koaUE=">
<script defer src="/cn.search.min.8d2462c3b745732864d843e8e2e7782a2ec838ca90fb94676baa461536bdae11.js" integrity="sha256-jSRiw7dFcyhk2EPo4ud4Ki7IOMqQ&#43;5Rna6pGFTa9rhE="></script>
<link rel="alternate" type="application/rss+xml" href="/docs/other/tools/index.xml" title="Home" />
<!--
Made with Book Theme
https://github.com/alex-shpak/hugo-book
-->

  
</head>

<body>
  <input type="checkbox" class="hidden" id="menu-control" />
  <main class="container flex">
    <aside class="book-menu">
      
  <nav>
<h2 class="book-brand">
  <a href="/"><img src="/logo.png" alt="Logo" /><span>Home</span>
  </a>
</h2>


<div class="book-search">
  <input type="text" id="book-search-input" placeholder="搜索" aria-label="搜索" maxlength="64" data-hotkeys="s/" />
  <div class="book-search-spinner spinner hidden"></div>
  <ul id="book-search-results"></ul>
</div>











  <ul>
<li><strong>计算机基础</strong>
<ul>
<li><a href="/docs/sicp/hardware/">硬件</a></li>
<li><a href="/docs/sicp/software/">软件</a></li>
<li><a href="/docs/sicp/program/">程序</a></li>
<li><a href="/docs/sicp/asm/">汇编</a></li>
</ul>
</li>
<li><strong>GO语言</strong>
<ul>
<li><a href="/docs/go/map/">字典</a></li>
<li><a href="/docs/go/closure/">闭包</a></li>
<li><a href="/docs/go/defer/">延迟调用</a></li>
<li><a href="/docs/go/goroutine/">并发调度</a></li>
<li><a href="/docs/go/alloc/">内存分配</a></li>
<li><a href="/docs/go/gc/">垃圾回收</a></li>
<li><a href="/docs/go/lock/">锁</a></li>
</ul>
</li>
<li><strong>Python语言</strong>
<ul>
<li><a href="/docs/python/memory/">内存管理</a></li>
<li><a href="/docs/python/interpreter/">解释器</a></li>
<li><a href="/docs/python/tools/">技巧工具</a></li>
</ul>
</li>
<li><strong>Mysql</strong>
<ul>
<li><a href="/docs/mysql/query/">查询</a></li>
<li><a href="/docs/mysql/theory/">原理</a></li>
</ul>
</li>
<li><strong>其他</strong>
<ul>
<li><a href="/docs/other/git/">git</a></li>
<li><a href="/docs/other/docker/">docker</a></li>
<li><a href="/docs/other/raft/">raft</a></li>
<li><a href="/docs/other/shell/">shell</a></li>
<li><a href="/docs/other/oop/">面向对象</a></li>
<li><a href="/docs/other/protocol/">网络协议</a></li>
<li><a href="/docs/other/tools/"class=active>系统工具</a></li>
</ul>
</li>
</ul>










</nav>




  <script>(function(){var menu=document.querySelector("aside.book-menu nav");addEventListener("beforeunload",function(event){localStorage.setItem("menu.scrollTop",menu.scrollTop);});menu.scrollTop=localStorage.getItem("menu.scrollTop");})();</script>


 
    </aside>

    <div class="book-page">
      <header class="book-header">
        
  <div class="flex align-center justify-between">
  <label for="menu-control">
    <img src="/svg/menu.svg" class="book-icon" alt="Menu" />
  </label>

  <strong>常用工具整理</strong>

  <label for="toc-control">
    <img src="/svg/toc.svg" class="book-icon" alt="Table of Contents" />
  </label>
</div>


  
    <input type="checkbox" class="hidden" id="toc-control" />
    <aside class="hidden clearfix">
      
  <nav id="TableOfContents">
  <ul>
    <li><a href="#体检工具">体检工具</a>
      <ul>
        <li><a href="#dstat">dstat</a></li>
        <li><a href="#sysstat">sysstat</a></li>
        <li><a href="#strace">strace</a></li>
      </ul>
    </li>
    <li><a href="#开发工具">开发工具</a>
      <ul>
        <li><a href="#readelf">readelf</a></li>
        <li><a href="#size">size</a></li>
        <li><a href="#nm">nm</a></li>
        <li><a href="#strip">strip</a></li>
        <li><a href="#objcopy">objcopy</a></li>
        <li><a href="#objdump">objdump</a></li>
        <li><a href="#ldd">ldd</a></li>
        <li><a href="#vim">vim</a></li>
      </ul>
    </li>
    <li><a href="#调试工具">调试工具</a></li>
    <li><a href="#项目构建">项目构建</a>
      <ul>
        <li><a href="#构建工具">构建工具</a></li>
        <li><a href="#依赖管理">依赖管理</a></li>
        <li><a href="#持续集成">持续集成</a></li>
      </ul>
    </li>
  </ul>
</nav>


    </aside>
  
 
      </header>

      
      
  <article class="markdown"><h1 id="常用工具整理">常用工具整理</h1>
<h2 id="体检工具">体检工具</h2>
<p>生产环境不同于开发环境，生产环境往往是一个很干净的、只保留了相关依赖的环境，而且需要运行很长的时间。而开发环境属于实验室性质的，类库比较齐全，只跑个单元测试或者benchmark之类的，运行时间很短。所以开发环境中很小的问题比如内存泄漏几KB，在生产环境随着时间的累积或者成千上万的访问，可能会把垃圾回收器搞崩溃。这种情况如果我们不擅于使用工具可能找不到任何问题。</p>
<p>另外，开发环境我们可以使用100%的资源，但生产环境一定要预留一些资源用来做调度、预警之类的。</p>
<h3 id="dstat">dstat</h3>
<p>它能实时查看一些基本信息，默认情况下它会包括:</p>
<ul>
<li>CPU基本信息(用户使用时间、系统使用时间、空闲时间等)</li>
<li>磁盘基本信息(读、写)</li>
<li>网络基本信息(接受、发送)</li>
<li>换入换出信息</li>
<li>系统基本信息(中断的次数、上下文切换的次数)</li>
</ul>
<p>如下所示:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac $ dstat
You did not <span style="color:#66d9ef">select</span> any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
  <span style="color:#ae81ff">0</span>   <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">100</span>   <span style="color:#ae81ff">0</span>   0|2797B  597B|   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |  <span style="color:#ae81ff">90</span>   <span style="color:#ae81ff">236</span>
  <span style="color:#ae81ff">0</span>   <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">100</span>   <span style="color:#ae81ff">0</span>   0|   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> | <span style="color:#ae81ff">140</span>   <span style="color:#ae81ff">323</span>
  <span style="color:#ae81ff">0</span>   <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">100</span>   <span style="color:#ae81ff">0</span>   0|   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> | <span style="color:#ae81ff">163</span>   <span style="color:#ae81ff">376</span>
  <span style="color:#ae81ff">0</span>   <span style="color:#ae81ff">1</span> <span style="color:#ae81ff">100</span>   <span style="color:#ae81ff">0</span>   0|   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> |   <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span> | <span style="color:#ae81ff">169</span>   <span style="color:#ae81ff">391</span></code></pre></div></p>
<p>生产环境下我们程序出错的时候，应该先从大的方面入手定位到具体是哪个方面的问题，看看当前的系统环境有没有问题，是不是我们的程序在当前的系统环境下水土不服。比如程序是IO密集型的，系统中有另一个程序在和它抢磁盘资源等。可以通过<code>dstat --list</code>查看它能对哪些细分项目查看其情况。<a href="http://dag.wiee.rs/home-made/dstat/">查看更多使用示例</a></p>
<h3 id="sysstat">sysstat</h3>
<p>通过定位了系统中哪个方面的问题之后，接着我们应该去定位我们自己程序哪个方面有问题。sysstat可以根据单个进程去检查它的各个方面，比如说我们定位到是内存方面的问题，接着去看自己程序中内存的问题:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac $ pidstat -r -p <span style="color:#e6db74">`</span>pidof tmux<span style="color:#e6db74">`</span> <span style="color:#ae81ff">2</span>
Linux 4.9.184-linuxkit <span style="color:#f92672">(</span>cabd4e519687<span style="color:#f92672">)</span> 	12/09/19 	_x86_64_	<span style="color:#f92672">(</span><span style="color:#ae81ff">2</span> CPU<span style="color:#f92672">)</span>

10:02:38      UID       PID  minflt/s  majflt/s     VSZ     RSS   %MEM  Command
10:02:40        <span style="color:#ae81ff">0</span>        <span style="color:#ae81ff">35</span>      0.00      0.00   <span style="color:#ae81ff">27424</span>    <span style="color:#ae81ff">4000</span>   0.20  tmux: server
10:02:42        <span style="color:#ae81ff">0</span>        <span style="color:#ae81ff">35</span>      0.00      0.00   <span style="color:#ae81ff">27424</span>    <span style="color:#ae81ff">4000</span>   0.20  tmux: server
10:02:44        <span style="color:#ae81ff">0</span>        <span style="color:#ae81ff">35</span>      0.00      0.00   <span style="color:#ae81ff">27424</span>    <span style="color:#ae81ff">4000</span>   0.20  tmux: server
10:02:46        <span style="color:#ae81ff">0</span>        <span style="color:#ae81ff">35</span>      0.00      0.00   <span style="color:#ae81ff">27424</span>    <span style="color:#ae81ff">4000</span>   0.20  tmux: server</code></pre></div>
我们把tmux当做是自己写的某个程序，每2秒输出一次信息。minflt/s就代表一些小范围的缺页异常，可能是一些数据不需要了只要补上相应的物理内存即可。而majflt/s代表了需要从硬盘换入内存，这可能就意味着我们程序是不是有的任务优先级太低被操作系统换出到硬盘上了，我们可能需要通过系统调用告诉操作系统把某段内存锁死。</p>
<p>更详细的使用方法，请参考<a href="http://sebastien.godard.pagesperso-orange.fr/documentation.html">官方文档</a>。</p>
<h3 id="strace">strace</h3>
<p>接着我们可以深入到自己程序的逻辑中去，比如使用strace检查我们程序的系统调用。可能只是一个简单的程序:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-go" data-lang="go"><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>

<span style="color:#66d9ef">func</span> <span style="color:#a6e22e">main</span>() {
	println(<span style="color:#e6db74">&#34;hello world!&#34;</span>)
}</code></pre></div></p>
<p>却涉及到大量的系统调用:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac $ go build test.go
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac $ strace ~/.mac/test
execve<span style="color:#f92672">(</span><span style="color:#e6db74">&#34;/root/.mac/test&#34;</span>, <span style="color:#f92672">[</span><span style="color:#e6db74">&#34;/root/.mac/test&#34;</span><span style="color:#f92672">]</span>, 0x7ffec1a0b740 /* <span style="color:#ae81ff">14</span> vars */<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
arch_prctl<span style="color:#f92672">(</span>ARCH_SET_FS, 0x4c5650<span style="color:#f92672">)</span>       <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
sched_getaffinity<span style="color:#f92672">(</span>0, 8192, <span style="color:#f92672">[</span>0, 1<span style="color:#f92672">])</span>      <span style="color:#f92672">=</span> <span style="color:#ae81ff">16</span>
openat<span style="color:#f92672">(</span>AT_FDCWD, <span style="color:#e6db74">&#34;/sys/kernel/mm/transparent_hugepage/hpage_pmd_size&#34;</span>, O_RDONLY<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> -1 ENOENT <span style="color:#f92672">(</span>No such file or directory<span style="color:#f92672">)</span>
mmap<span style="color:#f92672">(</span>NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0x7fd246a01000
mmap<span style="color:#f92672">(</span>0xc000000000, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0xc000000000
mmap<span style="color:#f92672">(</span>0xc000000000, 67108864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0xc000000000
mmap<span style="color:#f92672">(</span>NULL, 33554432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0x7fd244a01000
mmap<span style="color:#f92672">(</span>NULL, 2164736, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0x7fd2447f0000
mmap<span style="color:#f92672">(</span>NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0x7fd2447e0000
mmap<span style="color:#f92672">(</span>NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> 0x7fd2447d0000
rt_sigprocmask<span style="color:#f92672">(</span>SIG_SETMASK, NULL, <span style="color:#f92672">[]</span>, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
sigaltstack<span style="color:#f92672">(</span>NULL, <span style="color:#f92672">{</span>ss_sp<span style="color:#f92672">=</span>NULL, ss_flags<span style="color:#f92672">=</span>SS_DISABLE, ss_size<span style="color:#f92672">=</span>0<span style="color:#f92672">})</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
sigaltstack<span style="color:#f92672">({</span>ss_sp<span style="color:#f92672">=</span>0xc000002000, ss_flags<span style="color:#f92672">=</span>0, ss_size<span style="color:#f92672">=</span>32768<span style="color:#f92672">}</span>, NULL<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
rt_sigprocmask<span style="color:#f92672">(</span>SIG_SETMASK, <span style="color:#f92672">[]</span>, NULL, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
gettid<span style="color:#f92672">()</span>                                <span style="color:#f92672">=</span> <span style="color:#ae81ff">394</span>
rt_sigaction<span style="color:#f92672">(</span>SIGHUP, NULL, <span style="color:#f92672">{</span>sa_handler<span style="color:#f92672">=</span>SIG_DFL, sa_mask<span style="color:#f92672">=[]</span>, sa_flags<span style="color:#f92672">=</span>0<span style="color:#f92672">}</span>, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
rt_sigaction<span style="color:#f92672">(</span>SIGHUP, <span style="color:#f92672">{</span>sa_handler<span style="color:#f92672">=</span>0x44d8f0, sa_mask<span style="color:#f92672">=</span>~<span style="color:#f92672">[]</span>, sa_flags<span style="color:#f92672">=</span>SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer<span style="color:#f92672">=</span>0x44da20<span style="color:#f92672">}</span>, NULL, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
rt_sigaction<span style="color:#f92672">(</span>SIGINT, NULL, <span style="color:#f92672">{</span>sa_handler<span style="color:#f92672">=</span>SIG_DFL, sa_mask<span style="color:#f92672">=[]</span>, sa_flags<span style="color:#f92672">=</span>0<span style="color:#f92672">}</span>, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
rt_sigaction<span style="color:#f92672">(</span>SIGINT, <span style="color:#f92672">{</span>sa_handler<span style="color:#f92672">=</span>0x44d8f0, sa_mask<span style="color:#f92672">=</span>~<span style="color:#f92672">[]</span>, sa_flags<span style="color:#f92672">=</span>SA_RESTORER|SA_ONSTACK|SA_RESTART|SA_SIGINFO, sa_restorer<span style="color:#f92672">=</span>0x44da20<span style="color:#f92672">}</span>, NULL, 8<span style="color:#f92672">)</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>

......</code></pre></div></p>
<p>打印输入输出必然会涉及系统调用，但如果我们使用一些第三方库时发现系统调用仍然很多，就可以去查找有没有优化替代的方案。</p>
<p>一般，我们查看一些摘要信息即可:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac $ strace -c ~/.mac/test
hello world!
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>           write
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">7</span>           mmap
  0.00    0.000000           <span style="color:#ae81ff">0</span>       <span style="color:#ae81ff">114</span>           rt_sigaction
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">6</span>           rt_sigprocmask
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">2</span>           clone
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>           execve
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">2</span>           sigaltstack
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>           arch_prctl
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>           gettid
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">3</span>           futex
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>           sched_getaffinity
  0.00    0.000000           <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">1</span>         <span style="color:#ae81ff">1</span> openat
------ ----------- ----------- --------- --------- ----------------
100.00    0.000000                   <span style="color:#ae81ff">140</span>         <span style="color:#ae81ff">1</span> total</code></pre></div></p>
<h2 id="开发工具">开发工具</h2>
<p>GNU通用的开发工具，也叫<strong>binutils</strong>，是一个标准，属于随身带的瑞士军刀，任何语言编写的程序都适用，但可能与语言自带的工具链细节上有些出入。<a href="https://www.gnu.org/software/binutils/">官方网站</a></p>
<p>它主要包括:</p>
<ul>
<li>readelf : 查看ELF文件信息。</li>
<li>objdump : 用户⽬标文件反汇编。</li>
<li>ldd : 查看目标文件的动态依赖库。</li>
<li>addr2line : 将地址转换为文件行号信息。</li>
<li>nm : 查看符号表。</li>
<li>strip : 删除符号表。</li>
<li>objcopy : 拷⻉数据到⽬标文件。</li>
<li>strings : 输出字符串。</li>
<li>size : 查看各段⼤小。</li>
</ul>
<p>当我们不熟悉一门语言写的程序时，我们可以把它翻译成汇编语言，在把汇编语言翻译成C语言，也许这个C语言无法运行，但方便了我们阅读和理解程序的思路。</p>
<h3 id="readelf">readelf</h3>
<p>查看elf文件的头部信息:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -h hello
ELF Header:
  Magic:   7f <span style="color:#ae81ff">45</span> 4c <span style="color:#ae81ff">46</span> <span style="color:#ae81ff">02</span> <span style="color:#ae81ff">01</span> <span style="color:#ae81ff">01</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>      // 魔法数，可以快速读取出来用于预判整个文件是不是一个合法的内容
  Class:                             ELF64          // ELF文件的格式
  Data:                              2<span style="color:#960050;background-color:#1e0010">&#39;</span>s complement, little endian  // 大小端情况
  Version:                           <span style="color:#ae81ff">1</span> <span style="color:#f92672">(</span>current<span style="color:#f92672">)</span>
  OS/ABI:                            UNIX - System V    // 哪个平台使用
  ABI Version:                       <span style="color:#ae81ff">0</span>
  Type:                              EXEC <span style="color:#f92672">(</span>Executable file<span style="color:#f92672">)</span>     // 哪种类型，可执行的还是需重定位的等
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4000b0       //入口地址
  Start of program headers:          <span style="color:#ae81ff">64</span> <span style="color:#f92672">(</span>bytes into file<span style="color:#f92672">)</span>
  Start of section headers:          <span style="color:#ae81ff">736</span> <span style="color:#f92672">(</span>bytes into file<span style="color:#f92672">)</span>
  Flags:                             0x0
  Size of this header:               <span style="color:#ae81ff">64</span> <span style="color:#f92672">(</span>bytes<span style="color:#f92672">)</span>
  Size of program headers:           <span style="color:#ae81ff">56</span> <span style="color:#f92672">(</span>bytes<span style="color:#f92672">)</span>
  Number of program headers:         <span style="color:#ae81ff">2</span>
  Size of section headers:           <span style="color:#ae81ff">64</span> <span style="color:#f92672">(</span>bytes<span style="color:#f92672">)</span>
  Number of section headers:         <span style="color:#ae81ff">8</span>
  Section header string table index: <span style="color:#ae81ff">7</span></code></pre></div></p>
<p>查看其执行时需要向内存(进程)中载入哪些信息:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -l hello
Elf file type is EXEC <span style="color:#f92672">(</span>Executable file<span style="color:#f92672">)</span>
Entry point 0x4000b0
There are <span style="color:#ae81ff">2</span> program headers, starting at offset <span style="color:#ae81ff">64</span>
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000000d5 0x00000000000000d5  R E    0x200000
  LOAD           0x00000000000000d8 0x00000000006000d8 0x00000000006000d8
                 0x000000000000000e 0x000000000000000e  RW     0x200000
 Section to Segment mapping:
  Segment Sections...
   <span style="color:#ae81ff">00</span>     .text
   <span style="color:#ae81ff">01</span>     .data</code></pre></div></p>
<p>查看其本身的section信息:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -S hello
There are <span style="color:#ae81ff">8</span> section headers, starting at offset 0x2e0:
Section Headers:
  <span style="color:#f92672">[</span>Nr<span style="color:#f92672">]</span> Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  <span style="color:#f92672">[</span> 0<span style="color:#f92672">]</span>                   NULL             <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">00000000</span>
       <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>
  <span style="color:#f92672">[</span> 1<span style="color:#f92672">]</span> .text             PROGBITS         00000000004000b0  000000b0
       <span style="color:#ae81ff">0000000000000025</span>  <span style="color:#ae81ff">0000000000000000</span>  AX       <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">16</span>
  <span style="color:#f92672">[</span> 2<span style="color:#f92672">]</span> .data             PROGBITS         00000000006000d8  000000d8
       000000000000000e  <span style="color:#ae81ff">0000000000000000</span>  WA       <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">4</span>
  <span style="color:#f92672">[</span> 3<span style="color:#f92672">]</span> .stab             PROGBITS         <span style="color:#ae81ff">0000000000000000</span>  000000e8
       <span style="color:#ae81ff">0000000000000084</span>  <span style="color:#ae81ff">0000000000000014</span>           <span style="color:#ae81ff">4</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">4</span>
  <span style="color:#f92672">[</span> 4<span style="color:#f92672">]</span> .stabstr          STRTAB           <span style="color:#ae81ff">0000000000000000</span>  0000016c
       <span style="color:#ae81ff">0000000000000009</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
  <span style="color:#f92672">[</span> 5<span style="color:#f92672">]</span> .symtab           SYMTAB           <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">00000178</span>
       <span style="color:#ae81ff">0000000000000108</span>  <span style="color:#ae81ff">0000000000000018</span>           <span style="color:#ae81ff">6</span>     <span style="color:#ae81ff">7</span>     <span style="color:#ae81ff">8</span>
  <span style="color:#f92672">[</span> 6<span style="color:#f92672">]</span> .strtab           STRTAB           <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">00000280</span>
       <span style="color:#ae81ff">0000000000000027</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
  <span style="color:#f92672">[</span> 7<span style="color:#f92672">]</span> .shstrtab         STRTAB           <span style="color:#ae81ff">0000000000000000</span>  000002a7
       <span style="color:#ae81ff">0000000000000036</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
Key to Flags:
  W <span style="color:#f92672">(</span>write<span style="color:#f92672">)</span>, A <span style="color:#f92672">(</span>alloc<span style="color:#f92672">)</span>, X <span style="color:#f92672">(</span>execute<span style="color:#f92672">)</span>, M <span style="color:#f92672">(</span>merge<span style="color:#f92672">)</span>, S <span style="color:#f92672">(</span>strings<span style="color:#f92672">)</span>, I <span style="color:#f92672">(</span>info<span style="color:#f92672">)</span>,
  L <span style="color:#f92672">(</span>link order<span style="color:#f92672">)</span>, O <span style="color:#f92672">(</span>extra OS processing required<span style="color:#f92672">)</span>, G <span style="color:#f92672">(</span>group<span style="color:#f92672">)</span>, T <span style="color:#f92672">(</span>TLS<span style="color:#f92672">)</span>,
  C <span style="color:#f92672">(</span>compressed<span style="color:#f92672">)</span>, x <span style="color:#f92672">(</span>unknown<span style="color:#f92672">)</span>, o <span style="color:#f92672">(</span>OS specific<span style="color:#f92672">)</span>, E <span style="color:#f92672">(</span>exclude<span style="color:#f92672">)</span>,
  l <span style="color:#f92672">(</span>large<span style="color:#f92672">)</span>, p <span style="color:#f92672">(</span>processor specific<span style="color:#f92672">)</span></code></pre></div></p>
<p>查看其section的内容，例如我们想看其<code>.data</code>段的，它是第2个段，可以使用16进制和字符串的方式:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -x <span style="color:#ae81ff">2</span> hello
Hex dump of section <span style="color:#e6db74">&#39;.data&#39;</span>:
  0x006000d8 68656c6c 6f2c2077 6f726c64 210a     hello, world!.
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -p <span style="color:#ae81ff">2</span> hello
String dump of section <span style="color:#e6db74">&#39;.data&#39;</span>:
  <span style="color:#f92672">[</span>     0<span style="color:#f92672">]</span>  hello, world!</code></pre></div></p>
<p>查看其符号表信息:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -s hello
Symbol table <span style="color:#e6db74">&#39;.symtab&#39;</span> contains <span style="color:#ae81ff">11</span> entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: <span style="color:#ae81ff">0000000000000000</span>     <span style="color:#ae81ff">0</span> NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000004000b0     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">1</span>
     2: 00000000006000d8     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">2</span>
     3: <span style="color:#ae81ff">0000000000000000</span>     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">3</span>
     4: <span style="color:#ae81ff">0000000000000000</span>     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">4</span>
     5: <span style="color:#ae81ff">0000000000000000</span>     <span style="color:#ae81ff">0</span> FILE    LOCAL  DEFAULT  ABS hello.s
     6: 00000000006000d8     <span style="color:#ae81ff">1</span> OBJECT  LOCAL  DEFAULT    <span style="color:#ae81ff">2</span> hello
     7: 00000000004000b0     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">1</span> _start
     8: 00000000006000e6     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> __bss_start
     9: 00000000006000e6     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> _edata
    10: 00000000006000e8     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> _end</code></pre></div></p>
<ul>
<li>ABS 表示无需链接器处理。</li>
<li>UND 表示在本地引用的外部全局符号。</li>
<li>COM 表示未初始化，比如分配在<code>.bss</code>的全局变量。</li>
<li>OBJECT 变量。</li>
</ul>
<p>此外，<code>-e</code>代表同时加上<code>-h -l -S</code>三个参数。</p>
<h3 id="size">size</h3>
<p>使用size可以快捷的查看其<code>.text</code>、<code>.data</code>、<code>.bss</code>段的大小:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">root@cabd4e519687:~/.mac# size test
   text	   data	    bss	    dec	    hex	filename
 783967	  10904	 121704	 916575	  dfc5f	test</code></pre></div>
dec表示这三个段加起来的大小，hex是把dec转换为16进制后的值。</p>
<h3 id="nm">nm</h3>
<p>使用nm也可查看其符号表信息:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ nm hello
00000000006000e6 D __bss_start
00000000006000e6 D _edata
00000000006000e8 D _end
00000000004000b0 T _start
00000000006000d8 d hello</code></pre></div>
<p>其中，<code>00000000006000e6</code>表示链接器安排给这个符号的虚拟内存地址；<code>D</code>表示它的类型，大写是全局的、可以跨文件访问到的，小写表示本地的。</p>
<h3 id="strip">strip</h3>
<p>使用strip可以剔除其符号表，减少文件本身的大小。默认为<code>-s</code>剔除的符号，也可以<code>-S</code>仅剔除掉调试用的符号。
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ strip -S hello
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -s hello
Symbol table <span style="color:#e6db74">&#39;.symtab&#39;</span> contains <span style="color:#ae81ff">8</span> entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: <span style="color:#ae81ff">0000000000000000</span>     <span style="color:#ae81ff">0</span> NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000006000d8     <span style="color:#ae81ff">1</span> OBJECT  LOCAL  DEFAULT    <span style="color:#ae81ff">2</span> hello
     2: 00000000004000b0     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">1</span>
     3: 00000000006000d8     <span style="color:#ae81ff">0</span> SECTION LOCAL  DEFAULT    <span style="color:#ae81ff">2</span>
     4: 00000000004000b0     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">1</span> _start
     5: 00000000006000e6     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> __bss_start
     6: 00000000006000e6     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> _edata
     7: 00000000006000e8     <span style="color:#ae81ff">0</span> NOTYPE  GLOBAL DEFAULT    <span style="color:#ae81ff">2</span> _end
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ strip -s hello
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -s hello
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ nm hello
nm: hello: no symbols</code></pre></div></p>
<h3 id="objcopy">objcopy</h3>
<p>可以在可执行文件中自己创建section，藏一些东西，比如背景mp3文件等。我们就可以用到objcopy工具:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ objcopy --add-section .abc<span style="color:#f92672">=</span>addr.c --set-section-flags .abc<span style="color:#f92672">=</span>noload,readonly hello hello2
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -S hello2
There are <span style="color:#ae81ff">5</span> section headers, starting at offset 0x190:
Section Headers:
  <span style="color:#f92672">[</span>Nr<span style="color:#f92672">]</span> Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  <span style="color:#f92672">[</span> 0<span style="color:#f92672">]</span>                   NULL             <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">00000000</span>
       <span style="color:#ae81ff">0000000000000000</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>
  <span style="color:#f92672">[</span> 1<span style="color:#f92672">]</span> .text             PROGBITS         00000000004000b0  000000b0
       <span style="color:#ae81ff">0000000000000025</span>  <span style="color:#ae81ff">0000000000000000</span>  AX       <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">16</span>
  <span style="color:#f92672">[</span> 2<span style="color:#f92672">]</span> .data             PROGBITS         00000000006000d8  000000d8
       000000000000000e  <span style="color:#ae81ff">0000000000000000</span>  WA       <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">4</span>
  <span style="color:#f92672">[</span> 3<span style="color:#f92672">]</span> .abc              PROGBITS         <span style="color:#ae81ff">0000000000000000</span>  000000e6
       <span style="color:#ae81ff">0000000000000088</span>  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
  <span style="color:#f92672">[</span> 4<span style="color:#f92672">]</span> .shstrtab         STRTAB           <span style="color:#ae81ff">0000000000000000</span>  0000016e
       000000000000001c  <span style="color:#ae81ff">0000000000000000</span>           <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">0</span>     <span style="color:#ae81ff">1</span>
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ readelf -p .abc hello2
String dump of section <span style="color:#e6db74">&#39;.abc&#39;</span>:
  <span style="color:#f92672">[</span>     0<span style="color:#f92672">]</span>  // 查看基址变址的寻址方式^J#include &lt;stdio.h&gt;^J^Jint main<span style="color:#f92672">(){</span>^J    int x<span style="color:#f92672">[</span>3<span style="color:#f92672">]</span>;^J    <span style="color:#66d9ef">for</span><span style="color:#f92672">(</span>int i<span style="color:#f92672">=</span>0;i&lt;3;i++<span style="color:#f92672">){</span>^J        x<span style="color:#f92672">[</span>i<span style="color:#f92672">]=</span> 0x22;^J</code></pre></div>
<p>我们为可执行文件hello新增了一个<code>.abc</code>的段，它的内容读取自<code>addr.c</code>文件，它的权限是只读的且无需载入的，并且把它另存为了hello2。此外，我们也可以使用别的文件的内容来更新某个section，或者对section进行重命名、删除等操作:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ objcopy --rename-section .abc<span style="color:#f92672">=</span>.demo hello2
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ objcopy --update-section .demo<span style="color:#f92672">=</span>makefile hello2
<span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ objcopy --remove-section .demo hello2</code></pre></div></p>
<h3 id="objdump">objdump</h3>
<p>主要用来查看反汇编代码，使用<code>objdump -d &lt;file&gt;</code>反汇编某文件<code>.text</code>段的内容，默认为att格式，可使用<code>-M</code>指定其他格式。
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh"><span style="color:#f92672">[</span>ubuntu<span style="color:#f92672">]</span> ~/.mac/assem $ objdump -M intel -d fr

fr:     file format elf64-x86-64


Disassembly of section .text:

00000000004000b0 &lt;_start&gt;:
  4000b0:	b8 <span style="color:#ae81ff">01</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>       	mov    eax,0x1
  4000b5:	<span style="color:#ae81ff">48</span> <span style="color:#ae81ff">85</span> c0             	test   rax,rax
  4000b8:	<span style="color:#ae81ff">75</span> 1b                	jne    4000d5 &lt;_start.exit&gt;

00000000004000ba &lt;_start.hello&gt;:
  4000ba:	b8 <span style="color:#ae81ff">01</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>       	mov    eax,0x1
  4000bf:	bf <span style="color:#ae81ff">01</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>       	mov    edi,0x1
  4000c4:	<span style="color:#ae81ff">48</span> be e0 <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">60</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> 	movabs rsi,0x6000e0
  4000cb:	<span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>
  4000ce:	ba 0e <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>       	mov    edx,0xe
  4000d3:	0f <span style="color:#ae81ff">05</span>                	syscall

00000000004000d5 &lt;_start.exit&gt;:
  4000d5:	b8 3c <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span> <span style="color:#ae81ff">00</span>       	mov    eax,0x3c
  4000da:	<span style="color:#ae81ff">48</span> <span style="color:#ae81ff">31</span> ff             	xor    rdi,rdi
  4000dd:	0f <span style="color:#ae81ff">05</span>                	syscall</code></pre></div></p>
<h3 id="ldd">ldd</h3>
<p>用来查看可执行文件依赖的动态链接库信息:
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ldd ./test

  linux-vdso.so.1 <span style="color:#f92672">(</span>0x00007ffcf79ec000<span style="color:#f92672">)</span>
  libc.so.6 <span style="color:#f92672">=</span>&gt; /lib/x86_64-linux-gnu/libc.so.6 <span style="color:#f92672">(</span>0x00007fa010663000<span style="color:#f92672">)</span>  <span style="color:#75715e"># 运行库</span>
  /lib64/ld-linux-x86-64.so.2 <span style="color:#f92672">(</span>0x00007fa01085b000<span style="color:#f92672">)</span>                   <span style="color:#75715e"># 动态链接器</span></code></pre></div></p>
<h3 id="vim">vim</h3>
<p>vim提供了多种操作模式，它的设计基于大多数时间都花在阅读、浏览和少量编辑:</p>
<ul>
<li>正常模式，默认的情况，在其他模式中使用<code>&lt;Esc&gt;</code>返回该模式</li>
<li>插入模式，用于插入文本，正常模式通过<code>i</code>进入</li>
<li>替换模式，用于替换文本，正常模式通过<code>R</code>进入</li>
<li>可视化模式，用于选中文本块，正常模式下<code>v</code>进入一般可视模式，<code>V</code>进入可视行模式，<code>&lt;ctrl&gt;+v</code>进入可视块模式</li>
<li>命令模式，用于执行命令，正常模式通过<code>:</code>进入</li>
</ul>
<p>移动时常用的快捷键:</p>
<ul>
<li>左下上右，<code>hjkl</code></li>
<li>词，下一个词<code>w</code>，下一个词尾<code>e</code>，上一个词初<code>b</code></li>
<li>行，该行头部<code>0</code>，该行尾部<code>$</code>，该行的第一个非空格字符<code>^</code></li>
<li>屏幕，屏幕首行<code>H</code>，屏幕中间<code>M</code>，屏幕底部<code>L</code></li>
<li>翻页，上翻<code>&lt;ctrl&gt;+u</code>，下翻<code>&lt;ctrl&gt;+d</code></li>
<li>文件，文件头部<code>gg</code>，文件尾部<code>G</code></li>
<li>某一行，<code>:{行数}</code>或<code>{行数}G</code></li>
<li>杂项，<code>%</code>匹配一些配对的地方，例如括号对，<code>/* */</code>注释对等</li>
<li>查找本行的下一个字符，<code>f{字符}</code>向前查找，<code>F{字符}</code>向后查找</li>
<li>全文搜索，<code>/{正则表达式}</code>回车，然后使用<code>n</code>跳转到下一个匹配的项，<code>N</code>跳转到上一个</li>
<li>计数，向前移动3个词<code>3w</code>，向下移动5行<code>5j</code>，删除7个词<code>7dw</code></li>
</ul>
<h2 id="调试工具">调试工具</h2>
<p>GNU通用的调试工具，也叫<strong>gdb</strong>。binutils属于静态的观察，而gdb就可以动态的观察到每一个汇编指令的执行。<a href="https://www.gnu.org/software/gdb/">官方网站</a></p>
<p>也可以使用一些带图形界面的类似工具，例如<a href="https://www.gdbgui.com/">gdbgui</a>。还有些<a href="https://kapeli.com/cheat_sheets/GDB.docset/Contents/Resources/Documents/index">cheatsheet</a>很好用。</p>
<p>常用指令</p>
<table>
<thead>
<tr>
<th>指令</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>info r</td>
<td>查看寄存器</td>
</tr>
<tr>
<td>info f</td>
<td>查看栈帧</td>
</tr>
<tr>
<td>info files</td>
<td>查看可执行文件的section(静态视图)</td>
</tr>
<tr>
<td>info proc mappings</td>
<td>查看可执行文件的segment(动态视图)</td>
</tr>
<tr>
<td>info var</td>
<td>查看全局变量</td>
</tr>
<tr>
<td>info locals</td>
<td>查看局部变量</td>
</tr>
<tr>
<td>info breakpoints</td>
<td>查看断点信息</td>
</tr>
<tr>
<td>bt</td>
<td>显示程序的栈</td>
</tr>
<tr>
<td>set disassembly-flavor intel</td>
<td>设置反汇编的风格为intel或att</td>
</tr>
<tr>
<td>disass</td>
<td>查看反汇编</td>
</tr>
<tr>
<td>layout src</td>
<td>显示源码窗口</td>
</tr>
<tr>
<td>display [var]</td>
<td>每次停下来时都会输出变量var的值，var可以设为寄存器</td>
</tr>
<tr>
<td>l [n]</td>
<td>查看第N行代码的上下五行</td>
</tr>
<tr>
<td>c</td>
<td>运行至下一断点或程序结束</td>
</tr>
<tr>
<td>p/x $[var]</td>
<td>以16进制输出变量var的值，也可输出表达式，不加<code>/x</code>为十进制</td>
</tr>
<tr>
<td>x/10xb [addr]</td>
<td>查看内存地址addr开始的10组数据，16进制的，单位是字节</td>
</tr>
</tbody>
</table>
<h2 id="项目构建">项目构建</h2>
<h3 id="构建工具">构建工具</h3>
<p>GNU的自动构建工具为<strong>make</strong>，有些像脚本语言，把一堆命令放一起批量执行。使用它做编译属于增量编译，即通过对比修改时间来判断是否需要重新执行。<a href="https://www.gnu.org/software/make/">官方网站</a></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-make" data-lang="make"><span style="color:#a6e22e">hello</span><span style="color:#f92672">:</span> hello.s
    nasm -g -f elf64 -o hello.o hello.s
    ld -o $@ hello.o

<span style="color:#a6e22e">phonytest</span><span style="color:#f92672">:</span> hello.s
    nasm -g -f elf64 -o hello.o hello.s

<span style="color:#a6e22e">clean</span><span style="color:#f92672">:</span>
    -rm *.o
    -rm hello
    
<span style="color:#a6e22e">.PHONY</span><span style="color:#f92672">:</span> phonytest
</code></pre></div>
<p>对于这段构建代码，<code>hello:</code>后的部分就是告诉它要去检查哪些文件的修改时间；<code>$@</code>就表示当前这段的目标<code>hello</code>，<code>$&lt;</code>表示这段的第一个依赖项，<code>$^</code>表示这段的所有依赖项；命令前加<code>-</code>表示该命令如有错误则忽略；<code>PHONY</code>是一个伪标签，上例中<code>make hello</code>会先检查文件是不是最新的再去执行命令，而<code>make phonytest</code>直接就执行命令了。另外，由于历史原因makefile只能使用tab来缩进，不能使用空格。</p>
<h3 id="依赖管理">依赖管理</h3>
<p>一个项目可能会依赖很多其他的项目，对于大多数语言来讲，都会有一些软件仓库或工具，这些仓库在某个地方托管着大量的依赖，而这些依赖的项目往往有很多不同的版本。</p>
<p>试想一下，如果你的项目使用了软件A中的某个函数，当软件A升级以后该函数也移除掉了，那么会造成你的项目也无法运行。版本控制就是为了解决这个问题，我们可以指定当前项目需要基于某个版本或者某个范围的版本构建。这样也许解决了项目的运行问题，但如果软件A出现了安全漏洞，需要进行升级，怎么样让依赖它的项目都进行升级呢？</p>
<p>因此，人们定义了一套比较常用的版本号标准，称为<a href="https://semver.org/">Semantic Version</a>。它使用<code>major.minor.patch</code>的形式，例如Python的<code>3.7.3</code>，其中:</p>
<ul>
<li>如果新的版本中没有改变任何API，应该将patch number递增</li>
<li>如果添加了API且改动是向后兼容的，应该将minor number递增</li>
<li>如果修改了API且它并不向后兼容，应将major number递增</li>
</ul>
<p>此外，依赖管理系统中往往会遇到锁文件(lock files)的概念。该文件中列出了当前项目每个依赖对应的具体版本号，它可以避免不必要的重新编译或者避免直接自动安装升级到最新的版本。</p>
<p>还有一种极端的依赖锁定叫vendoring，它把依赖的所有的代码拷贝到项目中，使你能够完全掌握代码的任意修改或者将自己的修改加进去。</p>
<h3 id="持续集成">持续集成</h3>
<p>随着项目规模越来越大，修改代码之后额外的工作也会越来越多，可能是上传新版的文档、上传编译后的文件、发布代码到Pypi、执行测试等等，这些工作都可以通过持续集成系统(Continuous integration)来解决。有很多成熟的工具，例如Travis CI、Github Actions等，它们的工作原理也类似，在仓库中添加一个文件，该文件用于描述当前仓库发生任何修改时，应该做什么。比较常见的规则是如果有人提交代码时，则执行测试套件。然后CI提供方会启动一个或多个虚拟机，执行你制定的规则，并且记录下来相关的执行结果。</p>
<p>常见的测试方法和术语，我们需要有个了解:</p>
<ul>
<li>Test suite，所有测试的统称</li>
<li>Unit test，单元测试，用于对某个封装的特性进行测试</li>
<li>Integration test，集成测试，针对系统的某一大部分，测试其不同的组件是否能协同工作</li>
<li>Regression test，回归测试，用于保证之前引发的bug不会复现</li>
<li>Mocking，使用假的数据，避免测试不相关的内容例如网络等造成影响</li>
</ul>
</article>
 
      

      <footer class="book-footer">
        
  <div class="flex justify-between">



  <div>
    
    <a class="flex align-center" href="https://github.com/hjlarry/hjlarry.github.io/commit/e6e6e623fd0675b105aaca282d5d85361b1f1a8f" title='最后修改者 hjlarry | April 16, 2021' target="_blank" rel="noopener">
      <img src="/svg/calendar.svg" class="book-icon" alt="Calendar" />
      <span>April 16, 2021</span>
    </a>
  </div>



  <div>
    <a class="flex align-center" href="https://github.com/hjlarry/hjlarry.github.io/edit/master/content/docs/other/tools/_index.md" target="_blank" rel="noopener">
      <img src="/svg/edit.svg" class="book-icon" alt="Edit" />
      <span>编辑本页</span>
    </a>
  </div>

</div>

 
        <br>
<div style="text-align: center;font-size:xx-small;">
    Powered by <a href="https://gohugo.io" target="_blank">Hugo</a> | Theme by <a
        href="https://github.com/alex-shpak/hugo-book" target="_blank">hugo-book</a>
</div>
      </footer>

      
  
  <div class="book-comments">
<div id="disqus_thread"></div>
<script type="application/javascript">
    var disqus_config = function () {
    
    
    
    };
    (function() {
        if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
            document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
            return;
        }
        var d = document, s = d.createElement('script'); s.async = true;
        s.src = '//' + "hjlarry" + '.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="https://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
</div>
  
 

      <label for="menu-control" class="hidden book-menu-overlay"></label>
    </div>

    
    <aside class="book-toc">
      
  <nav id="TableOfContents">
  <ul>
    <li><a href="#体检工具">体检工具</a>
      <ul>
        <li><a href="#dstat">dstat</a></li>
        <li><a href="#sysstat">sysstat</a></li>
        <li><a href="#strace">strace</a></li>
      </ul>
    </li>
    <li><a href="#开发工具">开发工具</a>
      <ul>
        <li><a href="#readelf">readelf</a></li>
        <li><a href="#size">size</a></li>
        <li><a href="#nm">nm</a></li>
        <li><a href="#strip">strip</a></li>
        <li><a href="#objcopy">objcopy</a></li>
        <li><a href="#objdump">objdump</a></li>
        <li><a href="#ldd">ldd</a></li>
        <li><a href="#vim">vim</a></li>
      </ul>
    </li>
    <li><a href="#调试工具">调试工具</a></li>
    <li><a href="#项目构建">项目构建</a>
      <ul>
        <li><a href="#构建工具">构建工具</a></li>
        <li><a href="#依赖管理">依赖管理</a></li>
        <li><a href="#持续集成">持续集成</a></li>
      </ul>
    </li>
  </ul>
</nav>

 
    </aside>
    
  </main>

  
</body>

</html>












